import * as THREE from "three";
import { SimulatorBase } from "./SimulatorBase";
import { SimulationFrame } from "./SimulationFrame";
import { spring } from "../../core/FunctionLibrary";

export class RelativeSpringSimulator extends SimulatorBase {

    public position: number;
    public velocity: number;
    public target: number;
    public lastLerp: number;
    public cache: SimulationFrame[];

    constructor ( fps: number, mass: number, damping: number, startPosition: number = 0, startVelocity: number = 0 ) {

        super( fps, mass, damping );

        this.position = startPosition;
        this.velocity = startVelocity;

        this.target = 0;

        this.lastLerp = 0;

        this.cache = [];

        for ( let i = 0; i < 2; i++ ) {
            this.cache.push( new SimulationFrame( startPosition, startVelocity ) );
        }
    }


    public simulate ( timeStep: number ): void {

        this.generateFrames( timeStep );

        const cache0 = this.cache[ 0 ];
        const cache1 = this.cache[ 1 ];
        const alpha = this.offset / this.frameTime;

        const lerp = THREE.MathUtils.lerp( cache0.position, cache1.position, alpha );

        this.position = lerp - this.lastLerp;
        this.lastLerp = lerp;

        this.velocity = THREE.MathUtils.lerp( cache0.velocity, cache1.velocity, alpha );

    }

    public getFrame ( isLastFrame: boolean ): SimulationFrame {

        const lastFrame = this.laseFrame() as SimulationFrame;

        const newFrame = Object.assign( {}, lastFrame );

        if ( isLastFrame ) {
            // 重置位置
            newFrame.position = 0;
            // 过度到下一帧
            this.lastLerp = this.lastLerp - lastFrame.position;
        }

        return spring( newFrame.position, this.target, newFrame.velocity, this.mass, this.damping );
    }

}